package com.elitel.common.utils;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

// every thread can use a util
@Data
@Slf4j
public class LogTraceUtil{

    private static final ThreadLocal<LogTracer> contextHolder = new ThreadLocal<>();

    public static void setLogTracer(LogTracer logTracer) {
        contextHolder.set(logTracer);
    }

    public static LogTracer getLogTracer() {
        LogTracer logTracer = contextHolder.get();
        if(logTracer == null)
            logTracer = new LogTracer();

        return logTracer;
    }

    public static void clearLogTracer() {
        getLogTracer().record();
        contextHolder.remove();
    }


    @Data
    public static class LogTracer{
        private String logTraceId;
        private String logTracerName;
        private Date startDate;
        private Date endDate;
        private long totalConsumeTime;
        private int taskStepNumber = 0;
        private List<LogTraceTask> logTraceTaskList = new LinkedList<>();

        public LogTracer(){
            startDate = new Date();
            logTraceId = "logTracer_" + startDate.getTime();
        }

        public void endRecord(){
            endDate = new Date();
            totalConsumeTime = endDate.getTime() - startDate.getTime();
        }

        public LogTraceTask recordTask(String message){
            LogTraceTask logTraceTask = new LogTraceTask();
            logTraceTask.setStepNumber(taskStepNumber++);
            logTraceTask.setMessage(message);
            logTraceTask.setTaskStartTime(new Date());
            logTraceTaskList.add(logTraceTask);
            return logTraceTask;
        }

        public void record(){
            endRecord();
            StringBuilder sb = new StringBuilder();
            sb.append("\r\n===========> \r\n logTracerName (").append(logTracerName).append(")")
                .append("\r\n startDate: ").append(XCommonUtils.formatDateToMillisecond(startDate))
                .append("\r\n endDate: ").append(XCommonUtils.formatDateToMillisecond(endDate))
                .append("\r\n totalConsumeTime: ").append(totalConsumeTime)
                .append("\r\n logTraceTaskList: ");

            logTraceTaskList.forEach(logTraceTask -> {
                    sb.append("\r\n   stepNumber: ").append(logTraceTask.getStepNumber())
                        .append("\r\n\t   message: ").append(logTraceTask.getMessage())
                        .append("\r\n\t   taskStartTime: ").append(XCommonUtils.formatDateToMillisecond(logTraceTask.getTaskStartTime()))
                        .append("\r\n\t   taskEndTime: ").append(XCommonUtils.formatDateToMillisecond(logTraceTask.getTaskEndTime()))
                        .append("\r\n\t   taskConsumeTime: ").append(logTraceTask.getTaskConsumeTime())
                        .append("\r\n\t   importParam: ").append(logTraceTask.getImportContent());
                });

            sb.append("\r\n<===========");
            log.info(sb.toString());
        }
    }

    // here is data structure
    @Data
    public static class LogTraceTask{
        private int stepNumber;
        private String message;
        private Date taskStartTime;
        private Date taskEndTime;
        private long taskConsumeTime;
        private Object importContent;

        public void endTask(){
            taskEndTime = new Date();
            taskConsumeTime = taskEndTime.getTime() - taskStartTime.getTime();
        }
    }

}
